package com.xique.door.project.miniprogram.biz.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xique.common.core.utils.DateUtils;
import com.xique.common.core.utils.OrikaUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.door.bean.dao.BuildHouseUserDAO;
import com.xique.door.bean.dao.BuildingDeviceDAO;
import com.xique.door.bean.domain.AccessDevice;
import com.xique.door.bean.domain.OpenDoorRecord;
import com.xique.door.bean.domain.User;
import com.xique.door.bean.domain.UserV1;
import com.xique.door.bean.search.AreaBuildingHouseSearch;
import com.xique.door.bean.search.build.BuildingDeviceListSearch;
import com.xique.door.bean.vo.area.AreaBuildingHouseVo;
import com.xique.door.biz.service.IDeviceBizService;
import com.xique.door.project.miniprogram.bean.request.MiniOpenDoorRecordRequest;
import com.xique.door.project.miniprogram.bean.request.MiniOpenDoorRequest;
import com.xique.door.project.miniprogram.bean.vo.MiniHouseDeviceListVO;
import com.xique.door.project.miniprogram.bean.vo.MiniHouseDeviceVO;
import com.xique.door.project.miniprogram.bean.vo.MiniOpenDoorRecordVO;
import com.xique.door.project.miniprogram.biz.service.IMiniDoorBizService;
import com.xique.door.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author shd
 * @create 2022/4/20 13:24
 */
@Service
public class MiniDoorBizServiceImpl implements IMiniDoorBizService {

    @Autowired
    private IBuildHouseUserService houseUserService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IBuildingDeviceService buildingDeviceService;

    @Autowired
    private IDeviceBizService deviceBizService;

    @Autowired
    private IOpenDoorRecordService openDoorRecordService;

    @Autowired
    private IBuildHouseService houseService;

    @Autowired
    private IAccessDeviceService accessDeviceService;

    @Override
    public AjaxResult getHouseDeviceList() {

        Long baseUserId = SecurityUtils.getBaseUserId();
        if (StringUtils.isNull(baseUserId)) {
            return AjaxResult.error("请登录");
        }
//        Long parkId = SecurityUtils.getParkId();
//        if (StringUtils.isNull(parkId)) {
//            return AjaxResult.error("请选择小区");
//        }
//        Long userId = SecurityUtils.getUserId();
//        if (StringUtils.isNull(userId)) {
//            return AjaxResult.error("您不属于该小区", Collections.singletonMap("list", new ArrayList()));
//        }
        User user = new User();
        user.setBaseUserId(baseUserId);
        List<User> listuser = userService.selectUserList(user);
        List<BuildHouseUserDAO> list = new ArrayList<>();
        listuser.forEach(item -> {
            List<BuildHouseUserDAO> buildHouseUserDAOList =
                    houseUserService.selectBuildHouseUserByUserIdAndHouseId(item.getId(), null);
            list.addAll(buildHouseUserDAOList);
        });

//        List<BuildHouseUserDAO> list =
//                houseUserService.selectBuildHouseUserByUserIdAndHouseId(userId, null);

        List<MiniHouseDeviceVO> vos = OrikaUtil.converts(list, MiniHouseDeviceVO.class);

        List<Long> buildingIds =
                list.stream().map(BuildHouseUserDAO::getBuildingId).distinct().collect(Collectors.toList());
        BuildingDeviceListSearch search = new BuildingDeviceListSearch();
        search.setBuildingIds(buildingIds);
        List<BuildingDeviceDAO> deviceList =
                buildingDeviceService.selectBuildingDeviceListWithDeviceInfo(search);
        Map<Long, List<BuildingDeviceDAO>> deviceMap =
                deviceList.stream()
                        .collect(
                                Collectors.toMap(
                                        BuildingDeviceDAO::getBuildingId,
                                        v -> new ArrayList<>(Arrays.asList(v)),
                                        (List<BuildingDeviceDAO> oldList, List<BuildingDeviceDAO> newList) -> {
                                            newList.forEach(
                                                    i -> {
                                                        if (i.getStatus() == null) {
                                                            i.setStatus("offline");
                                                        }
                                                    });
                                            oldList.addAll(newList);
                                            return oldList;
                                        }));

        vos.forEach(
                item -> {
                    if (StringUtils.isNotNull(deviceMap.get(item.getBuildingId()))) {
                        List<MiniHouseDeviceListVO> deviceListVOS =
                                OrikaUtil.converts(
                                        deviceMap.get(item.getBuildingId()), MiniHouseDeviceListVO.class);
                        item.setDeviceList(deviceListVOS);
                    }
                });

        return AjaxResult.success(Collections.singletonMap("list", vos));
    }

    @Override
    public AjaxResult openDoor(MiniOpenDoorRequest request) {

        UserV1 userV1 = userService.seleceteUserV(SecurityUtils.getBaseUserId(),request.getParkId(),request.getHouseId());

        AjaxResult result = deviceBizService.openDoor(request.getDevSn(), userV1.getId());
        if (AjaxResult.isError(result)) {
            return result;
        }
        // 开门记录
        OpenDoorRecord insert = new OpenDoorRecord();
        insert.setParkId(request.getParkId());
        insert.setUserId(userV1.getId());
        insert.setHouseId(request.getHouseId());
        insert.setDeviceId(request.getDeviceId());
        insert.setOpenTime(new Date());

        openDoorRecordService.save(insert);

        return result;
    }

    @Override
    public AjaxResult getOpenDoorRecord(MiniOpenDoorRecordRequest request) {
        Long baseUserId = SecurityUtils.getBaseUserId();
        if (StringUtils.isNull(baseUserId)) {
            return AjaxResult.error("请登录");
        }
//        Long parkId = SecurityUtils.getParkId();
//        if (StringUtils.isNull(parkId)) {
//            return AjaxResult.error("请选择小区");
//        }
//        Long userId = SecurityUtils.getUserId();
//        if (StringUtils.isNull(userId)) {
//            return AjaxResult.error("您不属于该小区", Collections.singletonMap("list", new ArrayList()));
//        }

        User user = new User();
        user.setBaseUserId(baseUserId);
        user.setParkId(request.getParkId());
        List<User> listuser = userService.selectUserList(user);

        Map<String, Object> map = new HashMap<>(2);
        map.put("list", new ArrayList<>());
        map.put("total", 0);
        if (listuser.size()>0) {
            request.setUserId(listuser.get(0).getId());
        }
        IPage<OpenDoorRecord> page = openDoorRecordService.selectRecordPage(request);
        List<OpenDoorRecord> list = page.getRecords();
        if (CollectionUtil.isEmpty(list)) {
            return AjaxResult.success(map);
        }

        List<MiniOpenDoorRecordVO> vos = OrikaUtil.converts(list, MiniOpenDoorRecordVO.class);

        List<String> houseIds =
                list.stream().map(v -> v.getHouseId().toString()).distinct().collect(Collectors.toList());
        AreaBuildingHouseSearch search = new AreaBuildingHouseSearch(houseIds);
        List<AreaBuildingHouseVo> houseVoList =
                houseService.selecAreaBuildingHouseInfoByCondition(search);
        Map<String, AreaBuildingHouseVo> houseVoMap =
                houseVoList.stream().collect(Collectors.toMap(AreaBuildingHouseVo::getHouseId, v -> v));

        List<Long> deviceIds =
                list.stream().map(OpenDoorRecord::getDeviceId).distinct().collect(Collectors.toList());
        List<AccessDevice> accessDeviceList = accessDeviceService.selectAccessDeviceByIds(deviceIds);
        Map<Long, String> accessDeviceMap = accessDeviceList.stream().collect(Collectors.toMap(AccessDevice::getId, AccessDevice::getName));

        vos.forEach(item -> {
            if (StringUtils.isNotNull(houseVoMap.get(item.getHouseId().toString()))) {
                AreaBuildingHouseVo vo = houseVoMap.get(item.getHouseId().toString());
                item.setAreaName(vo.getAreaName());
                item.setBuildingName(vo.getBuildingName());
                item.setHouseName(vo.getHouseName());
            }
            if (StringUtils.isNotNull(accessDeviceMap.get(item.getDeviceId()))) {
                item.setDeviceName(accessDeviceMap.get(item.getDeviceId()));
            }
            item.setMonth(DateUtils.parseDateToStr(DateUtils.YYYY_MM, item.getOpenTime()));
        });

        map.put("list", vos);
        map.put("total", page.getTotal());

        return AjaxResult.success(map);
    }
}
